using System;
using System.Text;
using System.Collections.Generic;

using SBPweb.Common.Authorization;
using SBPweb.Common.Caching;
using SBPweb.Common.Session;

using SBPweb.PROvibe.Resources.Warehouse.Site;

using SBPweb.PROvibe.Business.Logic;

namespace SBPweb.PROvibe.Business.Warehouse
{

	public class SiteFactory
	{

		#region Private static string constants

		private static string CACHEKEY_SITES = "Warehouse.Sites";
		private static string CACHEKEY_SITES_INDEX_ID = "Warehouse.Sites.Index.Id";
		private static string CACHEKEY_SITES_INDEX_NAME = "Warehouse.Sites.Index.Name";
		private static string CACHEKEY_SITES_INDEX_HOST = "Warehouse.Sites.Index.Host";

		private static string SESSIONKEY_SITES = "_Repository.Sites";

		#endregion

		#region Private fields

		private static SiteRepository mSiteRepository
		{
			get
			{
				SiteRepository ret = SessionHandler.Get<SiteRepository>(SESSIONKEY_SITES);

				if (ret == null)
				{
					ret = new SiteRepository(ConfigurationManager.ConnectionStrings.Warehouse);
					SessionHandler.Put<SiteRepository>(SESSIONKEY_SITES, ret);
				}

				return ret;
			}
		}

		#endregion

		#region Constructor logic

		private SiteFactory()
		{
		}

		#endregion

		#region Repository handler methods

		#region Create

		public static Entities.Site CreateSite(string name, string host, int themeId)
		{
			Resources.Entities.Site site = new Resources.Entities.Site();

			site.Host = host;
			site.Name = name;
			site.ThemeId = themeId;

			mSiteRepository.Add(site);

			return ConvertResourcesEntity(site);
		}

		#endregion

		#region Read

		public static List<Entities.Site> ReadSites()
		{
			bool isCached = ConfigurationManager.CacheExpirations.IsCachingUsed;

			if (isCached && CacheHandler.GetAccessLogClone().ContainsKey(CACHEKEY_SITES))
			{
				return CacheHandler.Retrieve<List<Entities.Site>>(CACHEKEY_SITES);
			}

			List<Entities.Site> sites = ConvertResourcesEntityList(mSiteRepository.GetSites());

			if (isCached)
			{
				CacheHandler.Store<List<Entities.Site>>(CACHEKEY_SITES, sites, ConfigurationManager.CacheExpirations.Warehouse.Sites);

				Dictionary<int, Entities.Site> indexId = new Dictionary<int, Entities.Site>();
				Dictionary<string, Entities.Site> indexName = new Dictionary<string, Entities.Site>();
				Dictionary<string, Entities.Site> indexHost = new Dictionary<string, Entities.Site>();

				foreach (Entities.Site site in sites)
				{
					indexId.Add(site.Id, site);
					indexName.Add(site.Name, site);
					indexHost.Add(site.Host, site); 
				}

				CacheHandler.Store<Dictionary<int, Entities.Site>>(CACHEKEY_SITES_INDEX_ID, indexId, ConfigurationManager.CacheExpirations.Warehouse.Sites);
				CacheHandler.Store<Dictionary<string, Entities.Site>>(CACHEKEY_SITES_INDEX_NAME, indexName, ConfigurationManager.CacheExpirations.Warehouse.Sites);
				CacheHandler.Store<Dictionary<string, Entities.Site>>(CACHEKEY_SITES_INDEX_HOST, indexHost, ConfigurationManager.CacheExpirations.Warehouse.Sites);
			}

			return sites;
		}

		public static Entities.Site ReadSiteById(int siteId)
		{
			bool isCached = ConfigurationManager.CacheExpirations.IsCachingUsed;
			Dictionary<int, Entities.Site> index = null;

			if (isCached && CacheHandler.GetAccessLogClone().ContainsKey(CACHEKEY_SITES_INDEX_ID))
			{
				index = CacheHandler.Retrieve<Dictionary<int, Entities.Site>>(CACHEKEY_SITES_INDEX_ID);
				if (index.ContainsKey(siteId))
				{
					return index[siteId];
				}
			}

			Resources.Entities.Site resource = mSiteRepository.GetSiteById(siteId);
            Entities.Site site = null;
            if (resource != null)
            {
                site = ConvertResourcesEntity(resource);
            }

			if (index != null)
			{
				index.Add(siteId, site);
			}

			return site;
		}

		public static Entities.Site ReadSiteByName(string siteName)
		{
			bool isCached = ConfigurationManager.CacheExpirations.IsCachingUsed;
			Dictionary<string, Entities.Site> index = null;

			if (isCached && CacheHandler.GetAccessLogClone().ContainsKey(CACHEKEY_SITES_INDEX_NAME))
			{
				index = CacheHandler.Retrieve<Dictionary<string, Entities.Site>>(CACHEKEY_SITES_INDEX_NAME);
				if (index.ContainsKey(siteName))
				{
					return index[siteName];
				}
			}

            Resources.Entities.Site resource = mSiteRepository.GetSiteByName(siteName);
			Entities.Site site = null;
            if (resource != null)
            {
                site = ConvertResourcesEntity(resource);
            }

			if (index != null)
			{
				index.Add(siteName, site);
			}

			return site;
		}

		public static Entities.Site ReadSiteByHost(string siteHost)
		{
			bool isCached = ConfigurationManager.CacheExpirations.IsCachingUsed;
			Dictionary<string, Entities.Site> index = null;

			if (isCached && CacheHandler.GetAccessLogClone().ContainsKey(CACHEKEY_SITES_INDEX_HOST))
			{
				index = CacheHandler.Retrieve<Dictionary<string, Entities.Site>>(CACHEKEY_SITES_INDEX_HOST);
				if (index.ContainsKey(siteHost))
				{
					return index[siteHost];
				}
			}

            Resources.Entities.Site resource = mSiteRepository.GetSiteByHost(siteHost);
            Entities.Site site = null;
            if (resource != null)
            {
                site = ConvertResourcesEntity(resource);
            }

			if (index != null)
			{
				index.Add(siteHost, site);
			}

			return site;
		}

		#endregion

		#region Update

		public static void UpdateSite(Entities.Site site)
		{
			mSiteRepository.Update(site);
		}

		#endregion

		#region Delete

		public static void DeleteSite(int siteId)
		{
			mSiteRepository.Remove(siteId);
		}

		public static void DeleteSite(Entities.Site site)
		{
			DeleteSite(site.Id);
		}

		#endregion

		#endregion

		#region Internal converter methods

		internal static List<Entities.Site> ConvertResourcesEntityList(List<Resources.Entities.Site> list)
		{
			return list.ConvertAll<Entities.Site>(new Converter<Resources.Entities.Site, Entities.Site>(ConvertResourcesEntity));
		}

		internal static Entities.Site ConvertResourcesEntity(Resources.Entities.Site site)
		{
			return new Entities.Site(site);
		}

		#endregion

	}

}